package com.example.mallsystem1104.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mallsystem1104.constants.Constants;
import com.example.mallsystem1104.entity.Good;
import com.example.mallsystem1104.entity.GoodStandard;
import com.example.mallsystem1104.entity.dto.GoodDTO;
import com.example.mallsystem1104.exception.ServiceException;
import com.example.mallsystem1104.mapper.GoodMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.mallsystem1104.constants.RedisConstants.GOOD_TOKEN_KEY;
import static com.example.mallsystem1104.constants.RedisConstants.GOOD_TOKEN_TTL;

/**
 * @Author zy
 * @Date 2024/12/10 17:54
 * @packageName:com.example.mallsystem1104.service
 * @ClassName:GoodService
 */
@Service
public class GoodService extends ServiceImpl<GoodMapper,Good> {

    @Autowired
    private GoodMapper goodMapper;
    @Resource
    private RedisTemplate<String,Good> redisTemplate;

    public Object findAll() {
        return goodMapper.findAllGoods();
    }

    public Object getGoodById(Long id) {
        //rediskey=good:id:3
        String rediskey=GOOD_TOKEN_KEY+id;
        //先从redis里查，如果有商品信息则返回前端
        ValueOperations<String, Good> valueOperations=redisTemplate.opsForValue();
        Good redisGood=valueOperations.get(rediskey);
        if(redisGood!=null){
            //更新redis过期时间
            redisTemplate.expire(rediskey,GOOD_TOKEN_TTL, TimeUnit.MINUTES);
            return redisGood;
        }

        //如果redis里没有商品信息，则从数据库里查
        LambdaQueryWrapper<Good> queryWrapper=new LambdaQueryWrapper<Good>();
        //Good里面是否有isdelete值等于false并且id=传进来的id的商品
        queryWrapper.eq(Good::getIsDelete,false);
        queryWrapper.eq(Good::getId,id);

        //有的话则用Good接收返回
        Good dbGood=getOne(queryWrapper);

        //判断good是否为空，若不为空则把商品信息传回redis
        if(dbGood!=null){
            //将商品信息存入redis
            valueOperations.set(rediskey,dbGood);
            redisTemplate.expire(rediskey,GOOD_TOKEN_TTL,TimeUnit.MINUTES);
            return dbGood;
        }
    throw new ServiceException(Constants.NO_RESULT,"无结果");
    }


    public String getStandardById(Long id) {

        List<GoodStandard> standards=goodMapper.getStandById(id);
        if(standards.size()==0){
            throw new ServiceException(Constants.NO_RESULT,"无结果");
        }
        return JSON.toJSONString(standards);
    }


    //分页查询
    public Object findPage(Integer pageName, Integer pageSize, String searchText, Integer categoryId) {
        //构造查询条件，对good表进行降序查询
        LambdaQueryWrapper<Good> queryWrapper= Wrappers.<Good>lambdaQuery().orderByDesc(Good::getId);
        //对名称和描述进行模糊查询
        if(StrUtil.isNotBlank(searchText)){
            queryWrapper.like(Good::getName,searchText).or().like(Good::getDescription,searchText).or().eq(Good::getId,searchText);
        }
        //查找目录id是否存在
        if(categoryId!=null){
            queryWrapper.eq(Good::getCategoryId,categoryId);
        }
        //筛除掉已被删除的商品
        queryWrapper.eq(Good::getIsDelete,false);
        //用mybatis的分页工具对返回的数据进行分页
        IPage<Good> page=this.page(new Page<>(pageName,pageSize),queryWrapper);
        //使用lamdba构造式把good转为dto
        IPage<GoodDTO> goodDTOIPage=page.convert(good -> {
            GoodDTO goodDTO=new GoodDTO();
            BeanUtils.copyProperties(good,goodDTO);
            return goodDTO;
        });
        //设置最低价格后返回前端，并在商品首页进行展示
        for (GoodDTO good:goodDTOIPage.getRecords()){
            good.setPrice(getMinPrice(good.getId()));
        }
        return goodDTOIPage;

    }

    private BigDecimal getMinPrice(Long id){
        return goodMapper.getMinPrice(id);
    }

    public Object saveOrUpdateGood(Good good) {
        if(good.getId()==null){
            DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            good.setCreateTime(df.format(LocalDateTime.now()));
            goodMapper.insertGood(good);
        }else {
            saveOrUpdate(good);
            redisTemplate.delete(GOOD_TOKEN_KEY+good.getId());
        }
        return good.getId();
    }

    public Object findFullPage(Integer pageNum, Integer pageSize, String searchText, Integer categoryId) {
        //构造查询条件，对good表进行降序查询
        LambdaQueryWrapper<Good> queryWrapper=Wrappers.<Good>lambdaQuery().orderByDesc(Good::getId);
        //对名称和描述进行模糊查询
        if(StrUtil.isNotBlank(searchText)){
            queryWrapper.like(Good::getName,searchText).or().like(Good::getDescription,searchText).or().eq(Good::getId,searchText);
        }
        //查找目录id是否存在
        if(categoryId!=null){
            queryWrapper.eq(Good::getCategoryId,categoryId);
        }
        //筛除掉已被删除的商品
        queryWrapper.eq(Good::getIsDelete,false);
        //用mybatis的分页工具对返回的数据进行分页
        IPage<Good> page=this.page(new Page<>(pageNum,pageSize),queryWrapper);
        for(Good good:page.getRecords()){
            good.setPrice(getMinPrice(good.getId()));
        }
        return page;
    }

    public Object serRecommend(Long id, Boolean isRecommend) {
        LambdaUpdateWrapper<Good> goodLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
        goodLambdaUpdateWrapper.eq(Good::getId,id).set(Good::getRecommend,isRecommend);
        return update(goodLambdaUpdateWrapper);
    }

    public List<Good> getSaleRank(int num) {
        return goodMapper.getSaleRank(num);
    }
}